package com.cn.sl.server.api.system.user.model.dto

import com.cn.sl.server.api.system.user.service.LoginService
import jakarta.validation.Constraint
import jakarta.validation.ConstraintValidator
import jakarta.validation.ConstraintValidatorContext
import jakarta.validation.constraints.NotBlank
import org.dromara.hutool.extra.spring.SpringUtil
import org.springframework.messaging.handler.annotation.Payload
import kotlin.reflect.KClass

@RePasswordCheck
class UpdatePasswordParam(
    @get:NotBlank(message = "原始密码不能为空")
    @get:OldPasswordCheck
    var oldPassword: String?,

    @get:NotBlank(message = "新密码不能为空")
    var newPassword: String?,
    @get:NotBlank(message = "确认新密码不能为空")
    var reNewPassword: String?
) {
    fun toDto(): UpdatePasswordDto {
        return UpdatePasswordDto(oldPassword!!, newPassword!!, reNewPassword!!)
    }
}

data class UpdatePasswordDto(
    val oldPassword: String,
    val newPassword: String,
    val reNewPassword: String
)

@Target(AnnotationTarget.FIELD, AnnotationTarget.PROPERTY_GETTER)
@Retention(AnnotationRetention.RUNTIME)
@Constraint(validatedBy = [OldPasswordCheckValidator::class])
annotation class OldPasswordCheck(
    val message: String = "旧密码不正确",
    val groups: Array<KClass<*>> = [],
    val payload: Array<KClass<out Payload>> = [],
)

class OldPasswordCheckValidator : ConstraintValidator<OldPasswordCheck, String> {
    override fun isValid(
        value: String?,
        context: ConstraintValidatorContext?
    ): Boolean {
        value?.let {
            val loginService = SpringUtil.getBean(LoginService::class.java)
            return loginService.checkPassword(CheckPasswordDto(it))
        } ?: return false
    }

}

@Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.RUNTIME)
@Constraint(validatedBy = [RePasswordCheckValidator::class])
annotation class RePasswordCheck(
    val message: String = "两次密码输入不一致",
    val groups: Array<KClass<*>> = [],
    val payload: Array<KClass<out Payload>> = [],
)

class RePasswordCheckValidator : ConstraintValidator<RePasswordCheck, UpdatePasswordParam> {
    override fun isValid(
        value: UpdatePasswordParam?,
        context: ConstraintValidatorContext?
    ): Boolean {
        val newPassword = value?.newPassword
        val reNewPassword = value?.reNewPassword
        return newPassword == reNewPassword
    }

}